#pragma once

#include <string>

#include <D3D10misc.h>

#include <DirectXMath.h>

#include "Timer.h"

struct IDXGIFactory;
struct ID3D10Device;
struct IDXGISwapChain;
struct ID3D10Texture2D;
struct ID3D10RenderTargetView;
struct ID3D10DepthStencilView;
struct ID3DX10Font;

namespace D3D10
{
    class D3DFramework
    {
    public:
    	D3DFramework(const HINSTANCE handleInstance);
    	virtual ~D3DFramework();

    	__forceinline HINSTANCE getAppInst() const;
    	__forceinline HWND getMainWnd() const;

    	int run();

    	virtual void init();
    	virtual void onResize(); // reset projection/etc
    	virtual void updateScene(const float deltaTime);
    	virtual void drawScene(); 
    	virtual LRESULT msgProc(UINT msg, WPARAM wParam, LPARAM lParam);

    protected:
    	void initMainWindow();
    	void initDirect3D();
    	
    protected:
		D3D10Utils::Timer mTimer;

    	std::wstring mFrameStats;
        std::wstring mMainWindowCaption;
    	
     	IDXGIFactory *mDXGIFactory;
		ID3D10Device *mDevice;
    	IDXGISwapChain *mSwapChain;
    	ID3D10Texture2D *mDepthStencilBuffer;
    	ID3D10RenderTargetView *mRenderTargetView;
    	ID3D10DepthStencilView *mDepthStencilView;
		
    	// Derived class should set these in derived constructor to customize starting values.
    	D3D10_DRIVER_TYPE mDriverType;
    	DirectX::XMFLOAT4A mClearColor;
    	
        HINSTANCE mAppInstance;
    	HWND mMainWindow;
            	
    	uint32_t mClientWidth;
    	uint32_t mClientHeight;

        // Code computes the average frames per second, and also the 
        // average time it takes to render one frame.
        uint32_t mElapsedFrames;
        float mElapsedTimeInSeconds;
    	
    	bool mIsPaused;
    	bool mIsMinimized;
    	bool mIsMaximized;
    	bool mResizing;
    };

    HINSTANCE D3DFramework::getAppInst() const
    {
    	return mAppInstance;
    }

    HWND D3DFramework::getMainWnd() const
    {
    	return mMainWindow;
    }
}
